ホームに戻る
出典 :
関連 :
目次 :
MVVMパターンとは
WPFで推奨されているデザインパターンで、Model - View - ViewModel の略。
外観( View )と、外観に関連づくデータモデル( ViewModel )を分離することで、堅牢で透過性の高いアプリケーションとすることを目論んでいる。
MVCとの関連
MVVMは、Webアプリで主に用いられるMVC( Model - View - Controler )から派生したパターンで、類似点も多い。
View が外観を、Model が外観に直接関連しないデータを取り扱うという点は共通である。
MVVMの構成

View はXAMLとコードビハインド(XAML.CS)から成り、外観を司る。
ViewModel は View とは独立しており、ViewModel のインスタンスが View の DataContext として関連づけられる。
これにより ViewModel のプロパティ(CLIプロパティ)と View の依存関係プロパティとが関連づけられ、
ViewModel の変更が View に伝播する。
この View と関連づけられた ViewModel のプロパティを「
変更通知プロパティ」と呼び、
View と ViewModel とのプロパティの関連づけを「
データバインディング」と呼ぶ。
逆に View に対するユーザの操作(イベント)は ViewModel の「
コマンド」に関連づけられ、ユーザ操作が ViewModel に伝播する。
(コマンドバインディング)
Model ( ViewModel ではない)は外観によらないデータおよび業務ロジックを指し、ViewModel に組み込まれることで外観に関連づけられる。
ファイル構成例

ウィンドウまたはユーザーコントロールごとに View と ViewModel を作成する。
View と連動させる ViewModel のプロパティは組み込み型を直接保持するか、必要な Model をインスタンス化する。
コマンドも同様に、それぞれの View で用いるもののインスタンスを ViewModel で保持する。
注意が必要な点
Visual Studioでウィンドウやユーザーコントロールを作成した際、対応するXAMLとコードビハインドは対で作成されるが、
ViewModel はいかなる場合も自動では作成されない(MVVMに準拠した構成とならない)。
このため、コードビハインドが ViewModel だと誤解されることも多いが誤りである。ViewModel はあくまで手動で作成する必要がある。
なお、MVVMパターンはコードビハインドの記述を最小限に留めることが推奨されている。
DataContext
やバインディングの指定はXAMLで行うことが可能で、ユーザアクションへの対応(イベント処理)もコマンドに委譲できる。
この場合、コードビハインドにはコンストラクタしか記述されない。
ViewModel の実装
ViewModel のプロパティ変化を View に通知 : 変更通知プロパティ
ViewModel で保持している情報が変化した際に View 側で何らかの動作を起こしたい(例えば、UIの表示を変更する)場合は、
ViewModel にINotifyPropertyChanged
インタフェースを実装したうえでPropertyChanged
イベントを発生させる。
View 側はPropertyChanged
イベントフックに、イベント発生時にコールしたいコールバック(イベントハンドラ)を登録する。
View 側のデータバインディングされたプロパティ(ターゲット)も PropertyChanged
を契機として変化するため、INotifyPropertyChanged
を実装しなければ連動しない。
(即ち、ViewModel と View の両方にINotifyPropertyChanged
を実装する必要がある。
ただし、ターゲットに指定されるコントロールの依存関係プロパティは通常INotifyPropertyChanged
を実装しているため、特殊な操作は必要ない。)
詳細はリンク先を参照。
View の操作を ViewModel に通知 : コマンド
UIへの操作を ViewModel に伝えたい場合はコマンドを使用する。詳細はリンク先を参照。
View と ViewModel の結合
任意のクラスを ViewModel として新たに作成し、View のDataContext
に設定する。
ViewModel : MainViewModel.cs
namespace Sample
{
// ViewModel の本体
class MainViewModel
{
// プロパティ
public string Message { get; set; } = "サンプルメッセージ";
}
}
View : MainWindow.xaml
<
Window
(略)
>
<!-- MainViewModel を DataContext に設定 -->
<
Window.DataContext>
<
local:MainViewModel />
</
Window.DataContext>
:
<!-- TextBlock.Text を DataContext ( MainViewModel )の Message とバインド -->
<
TextBlock Text=
"{Binding Message}" />
ここでは
MainViewModel
を
Window
の
DataContext
として設定している。
なお
local
は
MainViewModel
が属する名前空間(
Sample
)のエイリアスである。
MainViewModel
の
Message
プロパティを
TextBlock
の
Text
へとデータバインディングを行っているが、
MainViewModel
を
DataContext
として関連づけているため、プロパティ名(
Message
)のみを記述すればよい。
(
MainViewModel.Message
などとする必要は無い。詳細は
データバインディングを参照。)
View : MainWindow.xaml.cs
namespace Sample
{
public partial class MainWindow : Window
{
// コンストラクタ
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
}
}
DataContext
の指定はコードビハインドから行うことも可能(推奨されない)。
その場合はコンストラクタ中で ViewModel のインスタンスをDataContext
に代入する。
注意が必要な点
XAMLからDataContext
の指定を行う場合、呼び出せる ViewModel のコンストラクタはデフォルトコンストラクタ(引数の無いコンストラクタ)に限定される。
このため、デフォルトコンストラクタ以外を呼びたい場合はコードビハインドで指定を行うなど回避策をとる必要がある。
ViewModel 構築の支援
変更通知プロパティやコマンドを含めた ViewModel の実装は煩雑であるが、
ViewModel の構築を支援してくれるライブラリが複数存在し、それらを活用することでコードの記述を大幅に削減できる。
ReactivePropertyが代表的。詳細はリンク先を参照。